package org.urchr.beorganized.api.impl.xml;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;

import org.postgresql.util.Base64;
import org.urchr.beorganized.dao.NotesDAO;
import org.urchr.beorganized.dao.XMLDocumentBuilder;
import org.urchr.beorganized.dao.errors.DBErrorException;
import org.urchr.beorganized.dao.tables.Note;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;

public class XMLExportReader implements XMLReader{

	private ContentHandler contentHandler = null;
	private DTDHandler dtdHandler = null;
	private EntityResolver entityResolver = null;
	private ErrorHandler errorHandler = null;
	private Note root = null;
	private ZipOutputStream zipOutputStream = null;
	private ServletContext servletContext = null;
	
	public XMLExportReader(Note note, ZipOutputStream zipOutputStream, ServletContext servletContext) {
		this.root = note;
		this.zipOutputStream = zipOutputStream;
		this.servletContext = servletContext;
	}
	
	public ContentHandler getContentHandler() {
		return contentHandler;
	}

	public DTDHandler getDTDHandler() {
		return dtdHandler;
	}

	public EntityResolver getEntityResolver() {
		return entityResolver;
	}

	public ErrorHandler getErrorHandler() {
		return errorHandler;
	}

	public boolean getFeature(String name) throws SAXNotRecognizedException,
			SAXNotSupportedException {
		// TODO Auto-generated method stub
		return false;
	}

	public Object getProperty(String name) throws SAXNotRecognizedException,
			SAXNotSupportedException {
		// TODO Auto-generated method stub
		return null;
	}

	private void setAttribute(String name, Object value, AttributesImpl attributesImpl){
		if(value!=null){
			attributesImpl.addAttribute("", name, name, "CDATA", value.toString());
		}
	}
	
	private void sendNote(Note note) throws SAXException, IOException{
		AttributesImpl attributesImpl = new AttributesImpl();
		
		setAttribute("text", note.getName(), attributesImpl);
		setAttribute("type", ""+note.getType(), attributesImpl);
		setAttribute("customIcon", ""+note.getCustomIcon(), attributesImpl);		
		setAttribute("contentType", note.getContentType(), attributesImpl);
		setAttribute("fileName", note.getFileName(), attributesImpl);
		setAttribute("shareCode", note.getShareCode(), attributesImpl);
		setAttribute("recurrence", note.getRecurrence(), attributesImpl);
		setAttribute("completed", ""+(note.getCompleted()>0), attributesImpl);
		setAttribute("fileSize", ""+note.getFileSize(), attributesImpl);
		setAttribute("priority", ""+note.getPriority(), attributesImpl);
		setAttribute("sort", ""+note.getSort(), attributesImpl);
		setAttribute("sortType", ""+note.getSortType(), attributesImpl);
//		setAttribute("urgentLevel", ""+note.getUrgentLevel(), attributesImpl);
		setAttribute("url", note.getUrl(), attributesImpl);
		
		setAttribute("createDate", 
				Note.dateToUserISO(note.getCreateDate(), null, false, false), attributesImpl);
		setAttribute("editDate", 
				Note.dateToUserISO(note.getEditDate(), null, false, false), attributesImpl);
		setAttribute("startDate", 
				Note.dateToUserISO(note.getStartDate(), null, true, note.getType()==Note.TYPE_TASK),
				attributesImpl);
		setAttribute("endDate", 
				Note.dateToUserISO(note.getEndDate(), null, true, false), attributesImpl);
		
		InputStream stream = null;
		
		File file = new File(servletContext.getRealPath(
				NotesDAO.FILES_STORE+note.getShareCode()+".bin"));
		if(file.exists()){
//			System.out.println("File exists - from disk");
			stream = new BufferedInputStream(new FileInputStream(file));
		}else{
//			System.out.println("File not found - from DB");
			if(note.getData()!=null){
				stream = new ByteArrayInputStream(note.getData());
			}
		}
		if(stream!=null){
			zipOutputStream.putNextEntry(new ZipEntry(note.getShareCode()+".bin"));
			for (int c = stream.read(); c!=-1; c = stream.read()) {
				zipOutputStream.write(c);
			}
//			setAttribute("data", Base64.encodeBytes(note.getData()), attributesImpl);
		}
		setAttribute("tags", note.getTagsString(), attributesImpl);
		contentHandler.startElement("", "note", "note", attributesImpl);
		try {
			List<Note> children = NotesDAO.getChildrenList(note.getId(), true);
			for (Note note2 : children) {
				sendNote(note2);
			}
		} catch (DBErrorException e) {
			e.printStackTrace();
			throw new SAXException();
		}
		contentHandler.endElement("", "note", "note");
	}
	
	public void parse(InputSource input) throws IOException, SAXException {
		// TODO Auto-generated method stub
		contentHandler.startDocument();
		sendNote(root);
		contentHandler.endDocument();
	}

	public void parse(String systemId) throws IOException, SAXException {
		// TODO Auto-generated method stub
		
	}

	public void setContentHandler(ContentHandler handler) {
		this.contentHandler = handler;
	}

	public void setDTDHandler(DTDHandler handler) {
		this.dtdHandler = handler;
	}

	public void setEntityResolver(EntityResolver resolver) {
		this.entityResolver = resolver;
	}

	public void setErrorHandler(ErrorHandler handler) {
		this.errorHandler = handler;
	}

	public void setFeature(String name, boolean value)
			throws SAXNotRecognizedException, SAXNotSupportedException {
		// TODO Auto-generated method stub
	}

	public void setProperty(String name, Object value)
			throws SAXNotRecognizedException, SAXNotSupportedException {
		// TODO Auto-generated method stub		
	}

}
